<?php

namespace app\ctrl;

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use Yurun\Util\YurunHttp\Co\Batch;
use Yurun\Util\HttpRequest;

/**
 * 批量生成robots的内容，并返回每条结果
 */
class Robots extends \app\ctrl\BaseController
{

    /**
     * 显示提交域名视图
     */
    public function index()
    {
        // 输出详情html内容
        $view = new \core\lib\View(VIEWS);
        return $view->render('robots', [
            'v' => time(),
            'url' => env('APP_BASEURL') . 'robots/exec',
            'exporturl' => env('APP_BASEURL') . 'robots/export',
        ]);
    }

    /**
     * 导出Excel，根据数据md5值获取缓存数据
     */
    public function export()
    {
        $params = post();
        $this->validate($params, [
            'datamd5' => 'require',
        ]);

        // 获取缓存
        $cacheKey = 'robots:' . $params['datamd5'];
        $redis = new \core\lib\Redis();
        $list = $redis->get($cacheKey);
        if (empty($list)) {
            error('数据已过期，请重新提交并导出');
        }

        // 创建一个新的excel文档
        require_once(VENDOR . '/autoload.php');
        $spreadsheet = new Spreadsheet();
        // 获取当前操作sheet的对象
        $worksheet = $spreadsheet->getActiveSheet();
        // 设置当前sheet的标题
        $worksheet->setTitle('Robots生成明细-' . date('Ymd'));
        // 设置宽度为true,不然太窄了
        $spreadsheet->getActiveSheet()->getColumnDimension('A')->setAutoSize(true);
        $spreadsheet->getActiveSheet()->getColumnDimension('B')->setAutoSize(true);

        //设置第一条的标题
        $worksheet->setCellValue('A1', '域名')->setCellValue('B1', '结果');

        // 设置粗体
        $spreadsheet->getActiveSheet()->getStyle('A1:B1')->getFont()->setBold(true);

        // 定义颜色
        $colorSuccess = '5cb85c';
        $colorError = 'd9534f';

        // 开始赋值
        if ($list['items']) {
            foreach ($list['items'] as $k => $item) {
                $i = $k + 2;
                $worksheet->setCellValue("A{$i}", $item['domain'])
                    ->setCellValue("B{$i}", $item['res']);
                if ($item['code'] === 1) {
                    $spreadsheet->getActiveSheet()->getStyle("A{$i}:B{$i}")->getFont()->getColor()->setRGB($colorSuccess);
                } else {
                    $spreadsheet->getActiveSheet()->getStyle("A{$i}:B{$i}")->getFont()->getColor()->setRGB($colorError);
                }
            }
            $i = $i + 1;
            $worksheet->setCellValue("B{$i}", '总计：成功' . $list['stat']['success'] . '个，失败' . $list['stat']['error'] . '个');
        }

        // 注意这边文件名不能带中文
        $filename = 'robots-' . date('YmdHi');
        $format = 'xls';

        return downloadExcel($spreadsheet, $filename, $format);
    }

    /**
     * 处理批量提交的域名
     */
    public function exec()
    {
        set_time_limit(0);
        require_once(VENDOR . '/autoload.php');
        $options = [
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
        ];
        $stat = ['success' => 0, 'error' => 0];

        $params = post();
        $this->validate($params, [
            'domains' => 'require',
        ]);
        $domains = array_filter(explode("\n", $params['domains']));
        $domains = array_map(function ($v) {
            return trim($v);
        }, $domains);
        $domains = array_unique($domains);
        $md5 = md5($params['domains']);

        foreach ($domains as $domain) {
            // 组装url
            $url = strtolower($domain);
            if (!str_starts_with($url, 'http')) {
                $url = 'http://' . $url;
            }
            if (!str_ends_with($url, 'robots')) {
                $url .= '/robots';
            }
            $url = str_replace(' ', '+', $url);
            // 总时间不得超过3秒，连接时间不得超过1秒
            $req[] = (new HttpRequest)->options($options)->retry(2)->timeout(8000, 2000)->url($url);
            $urls[] = $url;
            $dms[] = $domain;
        }

        $errdomains = [];
        if (!empty($req)) {
            $result = Batch::run($req);
            foreach ($result as $k => $resp) {
                $url = trim($urls[$k]);
                $domain = $dms[$k];
                $statusCode = $resp->getStatusCode();
                $data[$k] = [
                    'domain' => $domain,
                    'code' => 0,
                    'res' => '',
                ];

                if ($statusCode === 403) {
                    $msg = '访问不了';
                    $data[] = $url . '|' . $msg;

                    // logger()->error(compact('url', 'msg'));
                    $data[$k]['res'] = '失败：，output=' . $msg;
                    $errDomains[$k] = $domain;
                    $stat['error'] += 1;
                    continue;
                }
                $output = $resp->getBody()->getContents();
                if (is_string($output) && str_contains($output, 'success') && mb_strlen($output) < 50) {
                    $data[$k]['code'] = 1;
                    $data[$k]['res'] = 'OK';
                    $stat['success'] += 1;
                } elseif (is_string($output) && str_contains($output, 'by subfile') && mb_strlen($output) < 60) {
                    $data[$k]['res'] = '失败[二级文件不存在，或二级存在但是只能生成一级robots，无需排查]';
                    $stat['error'] += 1;
                    $errDomains[$k] = $domain;
                } else {
                    // $msg = '请求robots链接返回错误';
                    // logger()->error(compact('msg', 'domain', 'output'));
                    $output = !empty($output) && mb_strlen($output) > 40 ? substr($output, 0, 40) . '...' : $output;
                    $data[$k]['res'] = '失败：，output=' . $output;
                    $errDomains[$k] = $domain;
                    $stat['error'] += 1;
                }
            }
        }

        $ret = ['stat' => $stat, 'datamd5' => $md5, 'items' => $data, 'errdomains' => !empty($errDomains) ? join("\n", $errDomains) : ''];

        // 缓存数据
        $redis = new \core\lib\Redis();
        $cacheKey = 'robots:' . $md5;
        $expireSeconds = 3600;
        $redis->set($cacheKey, json_encode($ret));
        $redis->expire($cacheKey, $expireSeconds);

        return $ret;
    }
}